package com.huangym.springredis.redis;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.Transaction;

/**
 * 散列类型（hash）、列表类型（list）、集合类型（set）、有序集合类型（sorted set）
 * 使用列表类型实现队列
 * @author huangym3
 * @time 2016年11月9日 上午11:25:43
 */
@Component
@SuppressWarnings({ "unchecked", "rawtypes" })
@Repository("jedisPools")
public class JedisPools {
	
	private static final Logger logger = LoggerFactory.getLogger(JedisPools.class);
	
	private static JedisPool pool = null;

	@Value("${jedis.host}")
	private String host;

	@Value("${jedis.port}")
	private Integer port;

	@Value("${jedis.pwd}")
	private String pwd;

	@Value("${jedis.timeout}")
	private Integer timeout;

	@Value("${jedis.continuetime}")
	private Integer continuetime;

	private JedisPools jedisPool = null;

	public JedisPools getInstance() {
		if (jedisPool == null) {
			jedisPool = new JedisPools();
		}
		return jedisPool;
	}

	/**
	 * 构建redis连接池
	 */
	public JedisPool getPool() {
		if (pool == null) {
			JedisPoolConfig config = new JedisPoolConfig();
			// 是否启用pool的jmx管理功能, 默认true
			config.setJmxEnabled(true);

			// 是否启用后进先出, 默认true
			config.setLifo(true);

			// 最大连接数, 默认8个
			config.setMaxTotal(100);

			// 最小空闲连接数, 默认0
			config.setMinIdle(0);

			// 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
			config.setMaxIdle(300);

			// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,
			// 默认-1
			config.setMaxWaitMillis(-1);

			// 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
			config.setMinEvictableIdleTimeMillis(1800000);

			// 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
			config.setNumTestsPerEvictionRun(3);

			// 对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数
			// 时直接逐出,不再根据MinEvictableIdleTimeMillis判断 (默认逐出策略)
			config.setSoftMinEvictableIdleTimeMillis(1800000);

			// 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
			config.setTimeBetweenEvictionRunsMillis(-1);

			// 在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的；
			config.setTestOnBorrow(true);

			if (!"".equals(pwd)) {
				pool = new JedisPool(config, host, port, timeout, pwd);
			} else {
				pool = new JedisPool(config, host, port, timeout);
			}
		}
		return pool;
	}

	/**
	 * 返还到连接池
	 * 
	 * @param redis
	 */
	@SuppressWarnings("deprecation")
	public static void returnResource(Jedis jedis) {
		if (jedis != null) {
			pool.returnResource(jedis);
		}
	}

	/**
	 * 保存String数据
	 * 
	 * @param key
	 *            标识符
	 * @param jsonString
	 *            保存的参数
	 * @param mtimeout
	 *            保存时间
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public boolean setString(String key, String jsonString, int mtimeout) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();

			jedis.set(key, jsonString);
			if (mtimeout != -1) {
				if (mtimeout == 0) {
					jedis.expire(key, continuetime);
				} else {
					jedis.expire(key, mtimeout);
				}
			}
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
		return true;
	}

	/**
	 * 保存Object数据
	 */
	@SuppressWarnings("deprecation")
	public boolean setObject(String key, Object object, int mtimeout) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();

			JSONArray testjson = JSONArray.fromObject(object);
			jedis.set(key, testjson.toString());
			if (mtimeout != -1) {
				if (mtimeout == 0) {
					jedis.expire(key, continuetime);
				} else {
					jedis.expire(key, mtimeout);
				}
			}
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
		return true;
	}
	
	/**
	 * 使用hashes存储对象
	 * @param key
	 * @param object
	 * @param mtimeout
	 * @return
	 */
	public boolean saveObject(String key, Object object, int mtimeout) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			Class c = object.getClass();
			Field[] fields = c.getDeclaredFields();
			Map<String, String> map = new HashMap<String, String>();
			for (Field field : fields) {
				field.setAccessible(true);
				Class fc = field.getType();
				String value = "";
				Object fValue = field.get(object);
				if (fValue == null) {
					map.put(field.getName(), value);
					continue ;
				}
				if (String.class.equals(fc)) {
					value = (String) field.get(object);
				} else if (Long.class.equals(fc)) {
					Long v = (Long) fValue;
					value = String.valueOf(v);
				} else if (Integer.class.equals(fc)) {
					Integer v = (Integer) fValue;
					value = String.valueOf(v);
				} else if (Double.class.equals(fc)) {
					Double v = (Double) fValue;
					value = String.valueOf(v);
				} else if (Float.class.equals(fc)) {
					Float v = (Float) fValue;
					value = String.valueOf(v);
				} else if (Boolean.class.equals(fc)) {
					Boolean v = (Boolean) fValue;
					value = String.valueOf(v);
				} else {
					logger.error("不支持的字段类型：" + fc.getName());
					value = fValue.toString();
				}
				map.put(field.getName(), value);
			}
			jedis.hmset(key, map);
			jedis.expire(key, mtimeout);
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}

	/**
	 * 获取json数据
	 */
	@SuppressWarnings("deprecation")
	public String getString(String key) {
		String value = null;
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			value = jedis.get(key);
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
		return value;
	}
	
	/**
	 * 获取队列列头元素
	 * @param key
	 * @return
	 */
	public String getQueue(String key) {
		List<String> value = null;
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			// 以阻塞方式读取列表元素
			value = jedis.brpop(0, key);
			// 按优先级，依次从key1、key2、key3...队列中获取一个元素
			// jedis.brpop(timeout, key1, key2, key3...);
			System.out.println(value.get(0));System.out.println(value.get(1));
			return value.get(1);
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
		return null;
	}
	
	/**
	 * 将元素放入队列
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean setQueue(String key, String value) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			jedis.lpush(key, value);
			System.out.println("set value:" + value);
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
	/**
	 * 更新自动释放内存时间
	 */
	@SuppressWarnings("deprecation")
	public boolean updatetime(String key, int time) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			if (time != 0) {
				jedis.expire(key, time);
			} else {
				jedis.expire(key, continuetime);
			}
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
		return true;
	}

	/**
	 * 删除数据
	 */
	@SuppressWarnings("deprecation")
	public boolean delString(String key) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			jedis.del(key);
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
		return true;
	}

	/**
	 * 取<T> T数据
	 */
	public <T> T getObject(String key, T t) {
		return getObject(key, t, 0);
	}

	/**
	 * 从redis中取key对应的对象，同时更新对象的超时销毁时间
	 * 
	 * @param key
	 * @param t
	 * @param time
	 *            超时时间
	 * @return
	 */
	public <T> T getObject(String key, T t, int time) {
		try {
			String loginjson = getString(key);
			if (loginjson == null) {
				return null;
			}
			// 如果设置有超时时间，则更新
			if (time > 0) {
				updatetime(key, time);
			}
			JSONObject json = JSONObject.fromObject(loginjson.substring(1,
					loginjson.length() - 1));
			Map<String, Class> classMap = new HashMap<String, Class>();
			// 存在List时，加入以下代码
			// 例子：classMap.put("roles", RoleDTO.class);
			t = (T) JSONObject.toBean(json, t.getClass(), classMap);
			return t;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public <T> T getObject2(String key, T t) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			Class c = t.getClass();
			Field[] fields = c.getDeclaredFields();
			String[] fieldNames = new String[fields.length];
			for (int i = 0; i < fields.length; i++) {
				fieldNames[i] = fields[i].getName();
			}
			List<String> values = jedis.hmget(key, fieldNames);
			for (int i = 0; i < fields.length; i++) {
				fields[i].setAccessible(true);
				Class fc = fields[i].getType();
				if (values.get(i) == null || (!String.class.equals(fc) && "".equals(values.get(i)))) {
					fields[i].set(t, null);
					continue ;
				}
				if (String.class.equals(fc)) {
					fields[i].set(t, values.get(i));
				} else if (Long.class.equals(fc)) {
					Long value = Long.valueOf(values.get(i));
					fields[i].set(t, value);
				} else if (Integer.class.equals(fc)) {
					Integer value = Integer.valueOf(values.get(i));
					fields[i].set(t, value);
				} else if (Double.class.equals(fc)) {
					Double value = Double.valueOf(values.get(i));
					fields[i].set(t, value);
				} else if (Float.class.equals(fc)) {
					Float value = Float.valueOf(values.get(i));
					fields[i].set(t, value);
				} else if (Boolean.class.equals(fc)) {
					Boolean value = Boolean.valueOf(values.get(i));
					fields[i].set(t, value);
				} else {
					logger.error("不支持的字段类型：" + fc.getName());
					fields[i].set(t, values.get(i));
				}
			}
			return t;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return null;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
	public boolean test(String key, String value) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			
			// 设置key 对应的值为string 类型的value。如果key 已经存在，返回0，nx 是not exist 的意思。
			jedis.setnx(key, value);
			
			int seconds = 10;
			// 设置key 对应的值为string 类型的value，并指定此键值对应的有效期。
			jedis.setex(key, seconds, value);
			
			int offset = 8;
			// 设置指定key 的value 值的子字符串。其中的offset 是指从下标为offset（包含offset）的字符开始替换
			jedis.setrange(key, offset, value);
			
			
			String key2 = "key2";
			String value2 = "value2";
			String key3 = "key3";
			String value3 = "value3";
			// 一次设置多个key 的值，成功返回ok 表示所有的值都设置了，失败返回0 表示没有任何值被设置。
			jedis.mset(key, value, key2, value2, key3, value3);
			
			// 一次设置多个key 的值，成功返回ok 表示所有的值都设置了，失败返回0 表示没有任何值被设置，但是不会覆盖已经存在的key。
			// 如果这条命令返回0，那么里面操作都会回滚，都不会被执行。（只要有任何一个key已经存在，都会执行失败。）
			jedis.msetnx(key, value, key2, value2, key3, value3);
			
			// 设置key 的值，并返回key 的旧值。如果key 不存在，那么将返回nil
			jedis.getSet(key, value);
			
			int startOffset = 0;
			int endOffset = 6;
			// 获取指定key 的value 值的子字符串。字符串左面下标是从0 开始的
			jedis.getrange(key, startOffset, endOffset);
			startOffset = -7;
			endOffset = -1;
			// 字符串右面下标是从-1 开始的。当下标超出字符串长度时，将默认为是同方向的最大下标
			jedis.getrange(key, startOffset, endOffset);
			
			// 一次获取多个key 的值，如果对应key 不存在，则对应返回nil。
			List<String> result = jedis.mget(key, key2, key3);
			System.out.println(result);
			
			
			// 对key 的值做加加操作,并返回新的值。注意incr 一个不是int 的value 会返回错误，incr 一个不存在的key，则设置key 为1
			jedis.incr(key);
			
			int integer = 5;
			// 同incr 类似，加指定值 ，key 不存在时候会设置key，并认为原来的value 是 0
			jedis.incrBy(key, integer);
			
			// 对key 的值做的是减减操作，decr 一个不存在key，则设置key 为-1
			jedis.decr(key);
			
			// 同decr，减指定值。decrby 完全是为了可读性，我们完全可以通过incrby 一个负值来实现同样效果，反之一样。
			jedis.decrBy(key, integer);
			
			
			// 给指定key 的字符串值追加value,返回新字符串值的长度。
			jedis.append(key, value);
			
			// 取指定key 的value 值的长度。
			jedis.strlen(key);
			
			// 选择数据库。Redis 数据库编号从0~15，我们可以选择任意一个数据库来进行数据的存取。
			int index = 2;
			jedis.select(index);
			
			// 返回当前数据库中key 的数目。
			jedis.dbSize();
			
			// 删除当前选择数据库中的所有key。
			jedis.flushDB();
			// 删除所有数据库中的所有key。
			jedis.flushAll();
			
			// 返回满足给定pattern 的所有key
			jedis.keys("h?llo");
			
			// 确认一个key 是否存在
			jedis.exists(key);
			
			// 将当前数据库中的key 转移到其它数据库中
			jedis.move(key, 1);
			
			// 移除给定key 的过期时间
			jedis.persist(key);
			
			// 随机返回key 空间的一个key
			jedis.randomKey();
			
			String oldkey = "oldkey";
			String newkey = "newkey";
			// 重命名key。如果oldkey和newkey相同，则返回错误；如果newkey已经存在，则会被覆盖。
			jedis.rename(oldkey, newkey);
			// 重命名key。如果newkey已经存在，则返回错误。
			jedis.renamenx(oldkey, newkey);
			
			// 返回值的类型
			jedis.type(key);
			
			// 事务控制
			Transaction transaction = jedis.multi();
			
			transaction.exec();
			
			transaction.discard();
			
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
	/**
	 * hashes 类型及操作
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean testHashes(String key, String value) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			
			String field = "field";
			// 设置hash field 为指定值，如果key 不存在，则先创建。
			jedis.hset(key, field, value);
			
			// 设置hash field 为指定值，如果key 不存在，则先创建。如果field 已经存在，返回0，nx 是not exist 的意思。
			jedis.hsetnx(key, field, value);
			
			// 获取指定的hash field。
			jedis.hget(key, field);
			
			Map<String, String> hash = new HashMap<String, String>();
			// 同时设置hash 的多个field。
			jedis.hmset(key, hash);
			
			String field2 = "filed2";
			String field3 = "filed3";
			// 获取全部指定的hash filed。
			List<String> ret = jedis.hmget(key, field, field2, field3);
			System.out.println(ret);
			
			int integer = 1;
			// 指定的hash filed 加上给定值。
			jedis.hincrBy(key, field, integer);
			
			// 测试指定field 是否存在。
			jedis.hexists(key, field);
			
			// 返回指定hash 的field 数量。
			jedis.hlen(key);
			
			// 删除全部指定的hash filed。
			jedis.hdel(key, field, field2, field3);
			
			// 返回hash 的所有field。
			Set<String> fields = jedis.hkeys(key);
			System.out.println(fields);
			
			// 返回hash 的所有value。
			List<String> values = jedis.hvals(key);
			System.out.println(values);
			
			// 获取某个hash 中全部的filed 及value。
			Map<String, String> hashes = jedis.hgetAll(key);
			System.out.println(hashes);
			
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
	/**
	 * lists 类型及操作
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean testLists(String key, String value) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			
			// 在key 对应list 的头部添加字符串元素
			jedis.lpush(key, value);
			
			// 在key 对应list 的尾部添加字符串元素
			jedis.rpush(key, value);
			
			// 从list 的头部删除元素，并返回删除元素
			jedis.lpop(key);
			
			// 从list 的尾部删除元素，并返回删除元素
			jedis.rpop(key);
			
			String pivot = "hello";
			// 在key 对应list 的特定位置之前或之后添加字符串元素
			jedis.linsert(key, LIST_POSITION.BEFORE, pivot, value);
			
			int index = 0;
			// 设置list 中指定下标的元素值(下标从0 开始)
			jedis.lset(key, index, value);
			
			int count = 3;
			// 从key 对应list 中删除count 个和value 相同的元素。
			// count>0 时，按从头到尾的顺序删除；count<0 时，按从尾到头的顺序删除；count=0 时，删除全部。
			jedis.lrem(key, count, value);
			
			int start = 1;
			int end = -1;
			// 保留指定key 的列表指定下标范围内的数据。（保留列表指定下标范围内的值）
			jedis.ltrim(key, start, end);
			// 返回指定key 的列表指定下标范围内的数据。
			jedis.lrange(key, start, end);
			
			String srckey = "key1";
			String dstkey = "key2";
			// 从第一个list 的尾部移除元素并添加到第二个list 的头部,最后返回被移除的元素值，整个操作是原子的.如果第一个list 是空或者不存在返回nil
			jedis.rpoplpush(srckey, dstkey);
			
			// 返回名称为key 的list 中index 位置的元素
			jedis.lindex(dstkey, index);
			
			// 返回key 对应list 的长度
			jedis.llen(key);
			
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
	/**
	 * sets 类型及操作<BR>
	 * 关于set 集合类型除了基本的添加删除操作，其他有用的操作还包含集合的取并集(union)，交集(intersection)，差集(difference)。通过这些操作可以很容易的实现sns中的好友推荐和blog 的tag 功能。
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean testSets(String key) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			
			String member = "member";
			String member2 = "member2";
			String member3 = "member3";
			
			// 向名称为key 的set 中添加元素
			jedis.sadd(key, member, member2, member3);
			
			// 删除名称为key 的set 中的元素member
			jedis.srem(key, member, member2, member3);
			
			// 随机返回并删除名称为key 的set 中一个元素
			jedis.spop(key);
			jedis.spop(key, 2);
			
			String key2 = "key2";
			String key3 = "key3";
			String key4 = "key4";
			// 返回所有给定key 与第一个key 的差集
			jedis.sdiff(key, key2, key3, key4);
			
			String dstkey = "dstkey";
			// 返回所有给定key 与第一个key 的差集，并将结果存为另一个key
			jedis.sdiffstore(dstkey, key, key2, key3, key4);
			
			// 返回所有给定key 的交集
			jedis.sinter(key, key2, key3, key4);
			
			// 返回所有给定key 的交集，并将结果存为另一个key
			jedis.sinterstore(dstkey, key, key2, key3, key4);
			
			// 返回所有给定key 的并集
			jedis.sunion(key, key2, key3, key4);
			
			// 返回所有给定key 的并集，并将结果存为另一个key
			jedis.sunionstore(dstkey, key, key2, key3, key4);
			
			String srckey = "srckey";
			// 从第一个key 对应的set 中移除member 并添加到第二个对应set 中
			jedis.smove(srckey, dstkey, member);
			
			// 返回名称为key 的set 的元素个数
			jedis.scard(key);
			
			// 测试member 是否是名称为key 的set 的元素
			jedis.sismember(key, member);
			
			// 随机返回名称为key 的set 的一个元素，但是不删除元素
			jedis.srandmember(key);
			jedis.srandmember(key, 2);
			
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
	/**
	 * sorted sets 类型及操作
	 * @param key
	 * @return
	 */
	public boolean testSortedSets(String key) {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			
			String member = "member";
			String member2 = "member2";
			String member3 = "member3";
			Double score = 1.0;
			Double score2 = 2.0;
			Double score3 = 3.0;
			Map<String, Double> scoreMembers = new HashMap<String, Double>();
			scoreMembers.put(member, score);
			scoreMembers.put(member2, score2);
			scoreMembers.put(member3, score3);
			// 向名称为key 的zset 中添加元素member，score 用于排序。如果该元素已经存在，则根据score 更新该元素的顺序
			jedis.zadd(key, score, member);
			jedis.zadd(key, scoreMembers);
			
			// 删除名称为key 的zset 中的元素member
			jedis.zrem(key, member, member2, member3);
			Double start = 1.0;
			Double end = 3.0;
			// 删除集合中score 在给定区间的元素
			jedis.zremrangeByScore(key, start, end);
			
			// 如果在名称为key 的zset 中已经存在元素member，则该元素的score 增加increment；否则向集合中添加该元素，其score 的值为increment
			jedis.zincrby(key, score, member);
			
			// 返回名称为key 的zset 中member 元素的排名(按score 从小到大排序)即下标
			jedis.zrank(key, member);
			
			// 返回名称为key 的zset 中member 元素的排名(按score 从大到小排序)即下标
			jedis.zrevrank(key, member);
			
			// 返回名称为key 的zset（按score 从大到小排序）中的index 从start 到end 的所有元素
			int startIndex = 0;
			int endIndex = -1;
			jedis.zrevrange(key, startIndex, endIndex);
			
			// 返回集合中score 在给定区间的元素
			Double min = 0.0;
			Double max = 3.0;
			jedis.zrangeByScore(key, min, max);
			
			// 返回集合中score 在给定区间的数量
			jedis.zcount(key, min, max);
			
			// 返回集合中元素个数
			jedis.zcard(key);
			
			// 返回给定元素对应的score
			jedis.zscore(key, member);
			
			// 删除集合中排名在给定区间的元素
			jedis.zremrangeByRank(key, startIndex, endIndex);
			
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
	/**
	 * 发布/订阅
	 * @return
	 */
	public boolean PublishSubscribe() {
		JedisPool pool = null;
		Jedis jedis = null;
		try {
			pool = getPool();
			jedis = pool.getResource();
			
			String channel = "error";
			String channel2 = "message";
			jedis.subscribe(new JedisPubSub() {
				@Override
				public void onMessage(String channel, String message) {
					
				}
			}, channel, channel2);
			
			String message = "hello, world!";
			jedis.publish(channel, message);
			
			// 匹配方式批量订阅以tv开头的频道的内容
			String pattern = "tv*";
			jedis.psubscribe(new JedisPubSub() {
				@Override
				public void onMessage(String channel, String message) {
					
				}
			}, pattern);
			
			return true;
		} catch (Exception e) {
			// 释放redis对象
			pool.returnBrokenResource(jedis);
			e.printStackTrace();
			return false;
		} finally {
			// 返还到连接池
			returnResource(jedis);
		}
	}
	
}
